/* -------------------------------------------------------------------------- *
   TestWinUnit - Maria Blees (maria.blees@microsoft.com)

   File: FileLoggerTest.cpp

   Contains tests for the FileLogger class.  Uses TestableFileLogger
   to get access to protected members.
 * -------------------------------------------------------------------------- */

#include "WinUnit.h"

#include "TestableFileLogger.h"
#include "ReadableTempFile.h"

namespace
{
    wchar_t tempFilePath[MAX_PATH] = L"";
    const wchar_t* tempFileName = L"FileLoggerTest.txt";
    
    class FileObject
    {
    private:
        FILE* _file;
    public:
        FileObject(FILE* file) : _file(file) {}
        ~FileObject()
        {
            if (_file != NULL) { fclose(_file); }
        }
        operator FILE*() { return _file; }
    };

    FIXTURE(FileLoggerFixture);

    SETUP(FileLoggerFixture)
    {
        // Set up path for temporary file
        DWORD charCount = GetTempPathW(MAX_PATH, tempFilePath);
        WIN_ASSERT_WINAPI_SUCCESS(charCount != 0, _T("GetTempPath failed."));
        WIN_ASSERT_TRUE(charCount < MAX_PATH, 
            _T("Not enough buffer space for GetTempPath."));

#ifdef _UNICODE
        const wchar_t* errorFormatString = L"Unable to concatenate %s and %s.";
#else
        const char* errorFormatString = "Unable to concatenate %S and %S.";
#endif
        WIN_ASSERT_ZERO(wcsncat_s(tempFilePath, MAX_PATH, tempFileName, _TRUNCATE),
            errorFormatString, tempFilePath, tempFileName);
    }

    TEARDOWN(FileLoggerFixture)
    {
        // Delete temporary file if exists
        if (GetFileAttributesW(tempFilePath) != INVALID_FILE_ATTRIBUTES)
        {
            WIN_ASSERT_WINAPI_SUCCESS(DeleteFileW(tempFilePath));
        }

        // Clear path name
        ZeroMemory((void*)tempFilePath, MAX_PATH * sizeof(tempFilePath[0]));
    }

    BEGIN_TESTF(FileLoggerOutputsUnicodeStringCorrectly,
                FileLoggerFixture)
    {
        const wchar_t* str = L"Hello";
        // It's expected that it will be output as ANSI        
        {
            // Put in its own block so it will be flushed and closed.
            TestableFileLogger fileLogger;
#ifdef _UNICODE
            const wchar_t* errorFormatString = L"File could not be opened: %s.";
#else
            const char* errorFormatString = "File could not be opened: %S.";
#endif
            WIN_ASSERT_TRUE(fileLogger.OpenNewFile(tempFilePath),
                errorFormatString, tempFilePath);

            fileLogger.OutputUnicodeString(str);
        }

        // Now read the file and verify it contains what it should.
        FILE* file = NULL;
        WIN_ASSERT_ZERO(_wfopen_s(&file, tempFilePath, L"rtc"));
        WIN_ASSERT_NOT_NULL(file);

        FileObject fo(file);    // To ensure it will get closed.
        
        char buffer[1024] = ""; 
#pragma warning(push)
#pragma warning(disable : 6387) 
		// file cannot be NULL because an exception would have been thrown
		// above in WIN_ASSERT_NOT_NULL.
        WIN_ASSERT_NOT_NULL(fgets(buffer, ARRAYSIZE(buffer), file));
#pragma warning(pop)
		WIN_ASSERT_STRING_EQUAL("Hello", buffer);
    }
    END_TESTF

    BEGIN_TESTF(FileLoggerOutputsAnsiStringCorrectly,
                FileLoggerFixture)
    {
        const char* str = "Hello";
        {
            // Put in its own block so it will be flushed and closed.
            TestableFileLogger fileLogger;
#ifdef _UNICODE
            const wchar_t* errorFormatString = L"File could not be opened: %s.";
#else
            const char* errorFormatString = "File could not be opened: %S.";
#endif
            WIN_ASSERT_TRUE(fileLogger.OpenNewFile(tempFilePath),
                errorFormatString, tempFilePath);

            fileLogger.OutputAnsiString(str);
        }

        // Now read the file and verify it contains what it should.
        FILE* file = NULL;
        WIN_ASSERT_ZERO(_wfopen_s(&file, tempFilePath, L"rtc"));
        WIN_ASSERT_NOT_NULL(file);

        FileObject fo(file);    // To ensure it will get closed.
        
        char buffer[1024] = ""; 
#pragma warning(push)
#pragma warning(disable : 6387) 
		// file cannot be NULL because an exception would have been thrown
		// above in WIN_ASSERT_NOT_NULL.
        WIN_ASSERT_NOT_NULL(fgets(buffer, ARRAYSIZE(buffer), file));
#pragma warning(pop)
        WIN_ASSERT_STRING_EQUAL("Hello", buffer);        
    }
    END_TESTF

    BEGIN_TESTF(FileLoggerOutputsUnsignedIntCorrectly,
                FileLoggerFixture)
    {
        unsigned int n = UINT_MAX;
        {
            TestableFileLogger fileLogger;
#ifdef _UNICODE
            const wchar_t* errorFormatString = L"File could not be opened: %s.";
#else
            const char* errorFormatString = "File could not be opened: %S.";
#endif
            WIN_ASSERT_TRUE(fileLogger.OpenNewFile(tempFilePath),
                errorFormatString, tempFilePath);

            fileLogger.OutputUnsignedInt(n);
        }

        // Now read the file and verify it contains what it should.
        FILE* file = NULL;
        WIN_ASSERT_ZERO(_wfopen_s(&file, tempFilePath, L"rtc"));
        WIN_ASSERT_NOT_NULL(file);

        FileObject fo(file);    // To ensure it will get closed.
        
        char buffer[1024] = ""; 
#pragma warning(push)
#pragma warning(disable : 6387) 
		// file cannot be NULL because an exception would have been thrown
		// above in WIN_ASSERT_NOT_NULL.
        WIN_ASSERT_NOT_NULL(fgets(buffer, ARRAYSIZE(buffer), file));
#pragma warning(pop)
        WIN_ASSERT_STRING_EQUAL("4294967295", buffer);
    }
    END_TESTF
}